package impl

import (
	"context"
	"fmt"
	"time"

	"dario.cat/mergo"
	"gitee.com/liuxiaowei123/vblog-3/app/blog"
	"gorm.io/gorm"
)

type BlogServiceImpl struct {
	db *gorm.DB
}

var _ blog.BlogService = &BlogServiceImpl{}

// CreateBlog
func (b *BlogServiceImpl) CreateBlog(c context.Context, req *blog.CreateBlogRequest) (*blog.Blog, error) {
	// 1、构建blog实例
	ins := blog.NewBlog(req)

	// 2、保存blog到数据库
	err := b.db.WithContext(c).Create(ins).Error
	if err != nil {
		return nil, err
	}

	// 3、返回blog
	return ins, nil
}

// QueryBlog
func (b *BlogServiceImpl) QueryBlog(c context.Context, req *blog.QueryBlogRequest) (*blog.BlogSet, error) {
	// 1、创建查询
	query := b.db.WithContext(c).Model(&blog.Blog{})
	ins := blog.NewBlogSet()
	// 2、组合查询条件
	// 2.1、根据关键字查询
	if req.Keywords != "" {
		// 需要字符串拼接
		query = query.Where("title LIKE ?", "%"+req.Keywords+"%")
	}
	// 2.2、根据blog状态查询；通过指针是否为nil来判断
	if req.Status != nil {
		query = query.Where("status = ?", req.Status)
	}
	// 2.3、根据用户查询；通过切片的长度来判断
	if len(req.Usernames) > 0 {
		// gorm会自动把[]string 转换成功(xxx,xxx,xxx)
		query = query.Where("create_by in ? ", req.Usernames)
	}
	// 3、查询blog总数
	err := query.Count(&ins.Total).Error
	if err != nil {
		return nil, err
	}
	// 4、查询某一页的blog
	err = query.Order("created_at desc").Offset(req.Offset()).Limit(req.PageSize).Find(&ins.Item).Error
	if err != nil {
		return nil, err
	}
	return ins, nil
}

// DescribeBlog
func (b *BlogServiceImpl) DescribeBlog(c context.Context, req *blog.DescribeBlogRequest) (*blog.Blog, error) {
	// query := b.db.WithContext(c).Model(&blog.Blog{})
	ins := blog.NewBlog(blog.NewCreateBlogRequest())
	err := b.db.WithContext(c).Where("id = ?", req.BlogId).First(ins).Error
	if err != nil {
		return nil, err
	}

	return ins, nil
}

func (b *BlogServiceImpl) DeleteBlog(c context.Context, req *blog.DeleteBlogRequest) error {
	// 查询blog
	r := blog.NewDescribeBlogRequest()
	r.BlogId = req.BlogId
	ins, err := b.DescribeBlog(c, r)
	if err != nil {
		return err
	}
	// 删除blog
	err = b.db.WithContext(c).Where("id = ?", req.BlogId).Delete(ins).Error
	if err != nil {
		return err
	}
	return nil
}

// UpdateBlog
func (b *BlogServiceImpl) UpdateBlog(c context.Context, req *blog.UpdateBlogRequest) (*blog.Blog, error) {
	// 1、查询blog
	r := blog.NewDescribeBlogRequest()
	r.BlogId = req.BlogId
	ins, err := b.DescribeBlog(c, r)
	if err != nil {
		return nil, err
	}
	// 2、判断更新类型
	switch req.UpdateMode {
	case blog.UPDAET_PUT:
		ins.CreateBlogRequest = req.CreateBlogRequest
	case blog.UPDATE_PATCH:
		err := mergo.Merge(ins.CreateBlogRequest, req.CreateBlogRequest, mergo.WithOverride)
		if err != nil {
			return nil, err
		}
	default:
		return nil, fmt.Errorf("不符合更新类型%d,更新失败", req.UpdateMode)
	}
	// 3、更新blog
	ins.UpdatedAt = time.Now().Unix()
	err = b.db.WithContext(c).Updates(ins).Error
	if err != nil {
		return nil, err
	}
	// 4、返回更新后的blog
	return ins, nil
}

// AuditBlog
func (b *BlogServiceImpl) AuditBlog(c context.Context, req *blog.AuditBlogRequest) (*blog.Blog, error) {
	// 1、查询blog
	r := blog.NewDescribeBlogRequest()
	r.BlogId = req.BlogId
	ins, err := b.DescribeBlog(c, r)
	if err != nil {
		return nil, err
	}
	// 2、审核blog
	ins.AuditAt = time.Now().Unix()
	ins.IsAuditPass = req.IsAuditPass
	// 3、更新审核后的blog
	err = b.db.WithContext(c).Where("id = ?", req.BlogId).Updates(ins).Error
	if err != nil {
		return nil, err
	}
	return ins, nil
}
